iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0

前言

在上一篇文章中,我們第一次完整閱讀了一份Patient Resource,也看到了大量的大括號、中括號、冒號和逗號。

例如:

{
  "resourceType": "Patient",
  "id": "patient-example",
  "active": true
}

這種資料格式就是JSON。

FHIR並不是只能使用JSON,也可以使用XML等格式表達Resource。不過,JSON在Web API中非常常見,結構相對精簡,也方便搭配Postman及各種程式語言處理,因此本系列會以JSON作為主要示範格式。

今天先暫時放下複雜的FHIR欄位,專門認識JSON的基本語法,學會分辨Key、Value、Object、Array及常見資料型別。


JSON是什麼?

JSON的全名是:

JavaScript Object Notation

中文通常稱為JavaScript物件表示法。

雖然名稱中有JavaScript,但JSON不是只能在JavaScript中使用。它是一種輕量、文字形式,且不依賴特定程式語言的資料交換格式。

許多程式語言都能讀取及產生JSON,例如:

  • JavaScript
  • Java
  • Python
  • C#
  • Kotlin
  • Go
  • PHP

JSON經常被應用在:

  • Web API的Request
  • Web API的Response
  • 系統設定檔
  • 前端與後端之間的資料交換
  • 不同資訊系統之間的資料傳輸
  • FHIR Resource

它適合用來表達有結構的資料,也相對容易讓人閱讀。


FHIR只能使用JSON嗎?

FHIR並不只支援JSON。

常見的FHIR資料格式包括:

  • JSON
  • XML

同一筆Patient Resource可以使用不同格式呈現。

JSON格式

{
  "resourceType": "Patient",
  "id": "patient-001",
  "gender": "male"
}

XML格式

<Patient xmlns="http://hl7.org/fhir">
  <id value="patient-001"/>
  <gender value="male"/>
</Patient>

兩者表達的是相似資料,只是語法不同。

JSON與現代Web API的使用方式較接近,內容也通常比XML精簡,因此FHIR API經常使用JSON進行交換。

當系統傳送FHIR JSON時,常見的Content-Type是:

application/fhir+json

這是在告訴接收方:「這次傳送的內容是FHIR JSON資料。」


從最簡單的JSON開始

先看一份最簡單的病人資料:

{
  "name": "王小明",
  "gender": "male"
}

這份JSON由幾個基本符號組成:

符號 用途
{ } 表示Object
[ ] 表示Array
: 分隔Key與Value
, 分隔不同資料項目
" " 包住字串及Key

接下來逐一介紹。


Key與Value

JSON中的資料通常由Key與Value組成。

例如:

"name": "王小明"

其中:

  • "name"是Key
  • "王小明"是Value
  • 中間使用冒號:分隔

可以把它想成表單上的欄位名稱和填寫內容:

Key Value
name 王小明
gender male
birthDate 2000-01-01

將它們寫成JSON就是:

{
  "name": "王小明",
  "gender": "male",
  "birthDate": "2000-01-01"
}

在JSON中,Key必須是字串,因此需要使用雙引號包住。

正確寫法:

"name": "王小明"

錯誤寫法:

name: "王小明"

Object:用大括號包住的資料

Object使用大括號表示:

{
  "family": "王",
  "given": "小明"
}

Object中可以放入多組Key與Value,每一組之間使用逗號分隔。

上面的Object包含兩筆資料:

  1. family的值是
  2. given的值是小明

在FHIR中,許多欄位的Value本身也是Object。

例如,Patient的姓名可以寫成:

{
  "resourceType": "Patient",
  "name": {
    "family": "王",
    "given": "小明"
  }
}

這裡最外層是一個Object,而name的Value又是另一個Object。這種結構可以稱為巢狀Object。

不過,上面只是用來理解JSON的簡化示範。FHIR R4中的Patient.name實際上是可以重複的欄位,因此正式JSON需要使用Array表示。


Array:用中括號表示一組資料

Array使用中括號表示:

[
  "王小明",
  "王大明"
]

Array中可以放入多個值,每個值之間使用逗號分隔。

在FHIR Patient中,name是一個可以重複的欄位,因為同一個人可能同時具有正式姓名、舊名或暱稱。

因此,FHIR中的name會使用Array:

{
  "name": [
    {
      "use": "official",
      "text": "王小明"
    },
    {
      "use": "nickname",
      "text": "小明"
    }
  ]
}

這個name Array中包含兩個Object:

  • 第一個Object表示正式姓名。
  • 第二個Object表示暱稱。

如何分辨Object和Array?

可以直接看外面的括號:

Object

{
  "key": "value"
}

使用大括號{ },內容通常是Key與Value的組合。

Array

[
  "value1",
  "value2"
]

使用中括號[ ],內容是一組依照順序排列的值。

Array也可以放入多個Object:

[
  {
    "system": "phone",
    "value": "0900-000-001"
  },
  {
    "system": "email",
    "value": "patient@example.com"
  }
]

從FHIR Patient看Object和Array

以下是一份簡化的Patient Resource:

{
  "resourceType": "Patient",
  "id": "patient-example",
  "identifier": [
    {
      "system": "https://hospital.example.org/mrn",
      "value": "MRN0001"
    }
  ],
  "name": [
    {
      "family": "王",
      "given": [
        "小明"
      ]
    }
  ],
  "active": true
}

可以從最外層開始閱讀。

第一層:整份Resource是Object

最外面使用:

{
  ...
}

所以整份Patient Resource是一個Object。

第二層:identifier是Array

"identifier": [
  ...
]

identifier後面使用中括號,所以它的Value是一個Array。

第三層:Array中放入Object

{
  "system": "https://hospital.example.org/mrn",
  "value": "MRN0001"
}

identifier Array裡面放入一個Object。

name也是Array

"name": [
  {
    "family": "王",
    "given": [
      "小明"
    ]
  }
]

name是Array,裡面放入一個姓名Object。

given仍然是Array

"given": [
  "小明"
]

given也是Array,只是這次Array裡放的是字串,而不是Object。

FHIR JSON中經常出現Object包住Array、Array又包含Object的結構。閱讀時不需要一次看完整份資料,可以從最外層開始,一層一層往內拆解。


JSON有哪些Value資料型別?

JSON的Value不一定都是文字。

標準JSON可以表達以下幾種資料型別:

資料型別 範例
String "王小明"
Number 37.5
Boolean true
Null null
Object { "family": "王" }
Array ["小明"]

String:字串

String用來表示文字,必須使用雙引號包住。

"name": "王小明"
"birthDate": "2000-01-01"

雖然出生日期看起來和一般文字不同,但在JSON中仍然以字串表示。

FHIR會再針對欄位規定更明確的資料型別和格式,例如birthDate必須符合FHIR date的規則。

正確:

"gender": "male"

錯誤:

"gender": male

如果沒有雙引號,JSON會將male當成其他語法,而不是文字。


Number:數字

Number不需要使用雙引號。

"value": 37.5

如果將數字放進雙引號:

"value": "37.5"

它就會變成String,而不是Number。

兩者看起來很像,但資料型別不同:

JSON 資料型別
37.5 Number
"37.5" String

在FHIR中,欄位應使用哪一種資料型別會由規範決定,不能因為看起來相同就任意交換。


Boolean:布林值

Boolean只有兩個值:

true
false

例如:

"active": true

代表這筆Patient紀錄目前有效。

Boolean必須使用小寫,而且不需要雙引號。

正確:

"active": true

錯誤:

"active": "true"

上面的"true"是String。

錯誤:

"active": True

JSON中的Boolean不能寫成大寫開頭的True


Null:空值

標準JSON可以使用:

null

表示沒有值。

例如一般JSON可能出現:

{
  "middleName": null
}

不過,FHIR JSON對空值有自己的規則。FHIR欄位通常不應直接使用null,如果某個欄位沒有內容,一般會直接省略該欄位。

例如,不知道病人的電話時,通常不是寫:

"telecom": null

而是不要放入telecom

{
  "resourceType": "Patient",
  "id": "patient-example"
}

因此,要分清楚「JSON語法允許什麼」與「FHIR JSON規範允許什麼」。符合一般JSON語法,不一定代表符合FHIR。


巢狀結構是什麼?

JSON的Object和Array可以互相組合,形成多層結構。

例如:

{
  "resourceType": "Patient",
  "address": [
    {
      "use": "home",
      "text": "桃園市中壢區範例路100號"
    }
  ]
}

可以拆成:

  1. 最外層是Patient Object。
  2. address的Value是Array。
  3. Array中包含一個Address Object。
  4. Address Object中有usetext

這種一層包住另一層的形式,就是巢狀結構。

當FHIR Resource很長時,可以利用縮排觀察資料層級。


縮排會影響JSON嗎?

下面兩段JSON表達相同資料。

有縮排

{
  "resourceType": "Patient",
  "id": "patient-example",
  "active": true
}

沒有縮排

{"resourceType":"Patient","id":"patient-example","active":true}

空格、縮排和換行主要是為了方便人類閱讀,通常不會改變JSON資料的意義。

不過,在學習或除錯時,我會建議保留整齊縮排。當括號很多時,比較容易看出每一層Object和Array的範圍。


Object中的順序重要嗎?

在JSON Object中,欄位順序通常不影響資料意義。

下面兩份資料表達相同內容:

{
  "id": "patient-example",
  "active": true
}
{
  "active": true,
  "id": "patient-example"
}

但是,Array中的順序會被保留。

例如:

"given": [
  "小明",
  "大明"
]

第一個值與第二個值的位置仍然具有順序。

FHIR官方也說明,JSON Object屬性的順序沒有意義,但Array元素的順序需要保留。


JSON的Key有大小寫差異

JSON中的Key區分英文大小寫。

例如:

"resourceType": "Patient"

不能任意改成:

"resourcetype": "Patient"

也不能寫成:

"ResourceType": "Patient"

這三個Key對電腦來說並不相同。

FHIR已經定義好每個欄位的正式名稱,因此必須依照規範使用正確的英文大小寫。


JSON常見錯誤一:使用單引號

錯誤:

{
  'resourceType': 'Patient'
}

標準JSON的Key及String應使用雙引號。

正確:

{
  "resourceType": "Patient"
}

部分程式語言可能接受單引號,但那不代表它是符合標準的JSON。


JSON常見錯誤二:忘記逗號

錯誤:

{
  "resourceType": "Patient"
  "id": "patient-example"
}

resourceTypeid是兩組資料,中間需要使用逗號分隔。

正確:

{
  "resourceType": "Patient",
  "id": "patient-example"
}

JSON常見錯誤三:最後多一個逗號

錯誤:

{
  "resourceType": "Patient",
  "id": "patient-example",
}

最後一筆資料後面不能再放逗號。

正確:

{
  "resourceType": "Patient",
  "id": "patient-example"
}

JSON常見錯誤四:括號沒有成對

錯誤:

{
  "name": [
    {
      "text": "王小明"
    }
}

上面的name Array少了一個右中括號]

正確:

{
  "name": [
    {
      "text": "王小明"
    }
  ]
}

當JSON有多層巢狀結構時,縮排可以協助我們檢查每個括號是否成對。


JSON常見錯誤五:在JSON中加入註解

許多程式語言可以使用註解,但標準JSON本身不支援以下寫法:

{
  // 這是病人資料
  "resourceType": "Patient"
}

也不支援:

{
  "resourceType": "Patient" /* Resource類型 */
}

如果要說明欄位,應該寫在文章或程式文件中,不要直接把註解放入要傳送的JSON資料。


JSON語法正確,就代表FHIR正確嗎?

不一定。

下面是一份語法正確的JSON:

{
  "resourceType": "Patient",
  "favoriteFood": "蛋糕"
}

它可以被JSON工具正常讀取,但FHIR R4 Patient並沒有favoriteFood這個標準欄位。

另一個例子:

{
  "resourceType": "Patient",
  "active": "true"
}

這也是合法JSON,但active在FHIR中應該是Boolean,而不是String。

正確寫法是:

{
  "resourceType": "Patient",
  "active": true
}

因此,FHIR資料至少需要經過兩個層次的檢查:

第一層:JSON語法

  • 括號是否成對?
  • 是否使用雙引號?
  • 逗號位置是否正確?
  • Value是否符合JSON資料型別?

第二層:FHIR規範

  • Resource類型是否存在?
  • 欄位名稱是否正確?
  • 欄位資料型別是否符合規範?
  • 代碼是否合法?
  • 欄位出現次數是否正確?
  • 是否符合指定的Profile?

如何讓JSON更容易閱讀?

面對一大段FHIR JSON時,可以使用以下方法:

1. 先看resourceType

"resourceType": "Patient"

先確認這是哪一種Resource。

2. 觀察縮排

縮排越深,通常代表資料位於越內層的Object或Array。

3. 找大括號和中括號

  • { }是Object。
  • [ ]是Array。

4. 一次只讀一個欄位

不要一開始就想看懂整份Resource。可以先讀idnamebirthDate,再慢慢理解其他欄位。

5. 使用JSON格式化工具

Postman、程式編輯器及許多JSON工具都可以自動排版,讓巢狀結構更清楚。

但如果資料中包含真實病人資訊,不應任意貼到不確定安全性的公開網站進行格式化或驗證。


今日練習

請先觀察下面這份FHIR JSON:

{
  "resourceType": "Patient",
  "id": "patient-002",
  "active": true,
  "name": [
    {
      "use": "official",
      "family": "陳",
      "given": [
        "小華"
      ]
    }
  ],
  "telecom": [
    {
      "system": "email",
      "value": "patient@example.com"
    }
  ]
}

可以找出:

  1. 最外層是Object。
  2. resourceType的Value是String。
  3. active的Value是Boolean。
  4. name的Value是Array。
  5. name Array中包含一個Object。
  6. given仍然是一個Array。
  7. telecom Array中包含一筆電子郵件資料。

只要能夠分辨這些層次,就已經具備閱讀FHIR JSON的重要基礎。


今日小結

今天認識了JSON的基本結構,包括:

  • Key與Value
  • Object
  • Array
  • String
  • Number
  • Boolean
  • Null
  • 巢狀結構

也整理了幾個常見錯誤:

  • 使用單引號
  • 忘記逗號
  • 最後多放逗號
  • 括號沒有成對
  • 使用錯誤的大小寫
  • 在JSON中加入註解

FHIR雖然可以使用JSON表示,但符合JSON語法不代表一定符合FHIR規範。JSON只負責資料的基本表示方式,FHIR還會進一步規定欄位名稱、資料型別、代碼及出現次數。

下一篇將延續今天的內容,進一步認識FHIR自己的常見資料型別,了解為什麼姓名、地址、識別碼和醫療代碼不是單純的文字欄位。

明日預告

Day 10|FHIR常見資料型別一次看懂

參考資料

  1. RFC 8259:The JavaScript Object Notation(JSON)Data Interchange Format
    https://www.rfc-editor.org/rfc/rfc8259

  2. HL7 FHIR R4:JSON Format
    https://hl7.org/fhir/R4/json.html

  3. HL7 FHIR R4:Data Types
    https://hl7.org/fhir/R4/datatypes.html

  4. HL7 FHIR R4:Patient Resource
    https://hl7.org/fhir/R4/patient.html


上一篇
Day 8|第一次看FHIR Patient Resource
下一篇
Day 10|FHIR常見資料型別一次看懂
系列文
《醫資生的 FHIR 30日入門:用 Postman 讀懂醫療資料交換》30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言